#pragma once
#include <iostream>
#include <functional>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <cstring>
#include <cerrno>

#include <pthread.h>

#include "logMessage.hpp"
#include "err.hpp"
#include "Sock.hpp"

#define myself 1

#ifdef myself
#include "protocal.hpp"
#else
#include "JSON.hpp"
#endif



namespace ns_TcpServer
{
    class TcpServer;
    using func_t = std::function<ns_protocal::Response(ns_protocal::Request)>;


    class ThreadData
    {
    public:
        ThreadData(int sock, TcpServer *pts) : _sock(sock), _pTS(pts)
        {
        }

        int _sock;
        TcpServer *_pTS;

    };

    class TcpServer
    {
    public:
        TcpServer(func_t func, uint16_t port) : _func(func), _port(port)
        {
        }
        ~TcpServer()
        {
        }

        void InitServer()
        {
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();

            logMessage(Debug, "Init TcpServer success listenSock : %d", _listensock.Fd());
        }

        void StartServer()
        {
            while (true)
            {
                std::string clientip;
                uint16_t clientport;

                int sock = _listensock.Accept(&clientip, &clientport);
                if (sock < 0)
                    continue;

                logMessage(Info, "accept a user info : ip %s | port:%d", clientip.c_str(), clientport);

                pthread_t tid;
                ThreadData* td = new ThreadData(sock,this);
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData* pTD = static_cast<ThreadData*>(args);
            pTD->_pTS->serviceIO(pTD->_sock);


            delete pTD;
            return nullptr;
        }

        void serviceIO(int sock)
        {
            //TODO...
            std::string inbuffer;
            while(true)
            {
                //0.拿到一个完整的报文
                std::string package;
                int len = ns_protocal::ReadPackage(sock,inbuffer,&package);
                if(len == 0)
                {
                    continue;
                }
                else if(len < 0)
                {
                    break;
                }

                //1.提取有效载荷
                package = ns_protocal::RemoveHeader(package,len);

                //2.反序列化
                ns_protocal::Request req;
                req.Deserialize(package);

                //3.处理用户的请求
                ns_protocal::Response resp =_func(req);

                //4.序列化这个结构的resp
                std::string send_str;
                resp.Serialize(&send_str);

                //5.添加报头
                send_str = ns_protocal::AddHeader(send_str);
                

                std::cout << "发送中" << send_str <<std::endl;
                //6.发送
                send(sock,send_str.c_str(),send_str.size(),0);

                std::cout << "发送OK"<< send_str << std::endl;

            }
            close(sock);
        }

    private:
        uint16_t _port;
        Sock _listensock;
        func_t _func;
    };



}